////////////////////////////////////////
// LinkedListSortTester.cpp
//Name: Stephen Durfey && Chris Mares
//Class: CS335
//Prof: Dr. Michael Poor
//Date: 12/4/2008
//Purpose: This program implements the quick sort using a singly linked list. It accepts 2 command line arguments,
//		 as well as 2 flags. The first arugment specifies which file to read into the program.
//		 One flag specifies what type of data structure will be used. The other flag specifies to use a linked list.
//		 Firstly it will sort a list of city data (as specified by the user at the command line) using the quick sort.
//		 While quick sort is running, it will be timed. After the sorting is complete, and the time it ran is determined,
//		 it will print out the first 100 lines of sorted city data, keyed by the last string in the row. After this,
//		 the program will determine the memory footprint of the linked list and report it to the user.

#include <iostream>
#include <iomanip>
#include <fstream>
#include <ctime>
#include "stringUtil.h"
#include "SinglyLinkedList.cpp"
#include "LinkedListSort.cpp"
using namespace std;

inline bool before1(vector<string> & x, vector<string> & y)
{
    int     val1 = stringToInt(x[9]);
    int     val2 = stringToInt(y[9]);

    return val1 > val2;
}

inline bool before2(vector<string> * & x, vector<string> * & y)
{
    int     val1 = stringToInt((*x)[9]);
    int     val2 = stringToInt((*y)[9]);

    return val1 > val2;
}

int main(int argc, char *argv[])
{
    ifstream                            infile(argv[1]);
    clock_t                             start, finish;
    double                              time;
    int                                 space = 0, i;
    SinglyLinkedList<vector<string> >   aTable;
    SinglyLinkedList<vector<string> >::iterator  aIter;
    vector<string>                      line;
    SinglyLinkedList<vector<string> *>  bTable;
    SinglyLinkedList<vector<string> *>::iterator  bIter;
    vector<string>                      *row;

    switch (argv[2][0])
    {
    case 'a':  // bubblesort with elements
        while (readMultiwordVector(line, infile))
            aTable.push_front(line);
        for (aIter = aTable.begin(); aIter != aTable.end(); ++aIter)
        {
            for (int m = 0; m < (*aIter).size(); ++m)
                space += (*aIter)[m].size();
            space += sizeof(int *);
        }

        cout << "sorting..." << endl;
        start = clock();
        bubblesort(aTable, before1);
        finish = clock();
        for (i = 0, aIter = aTable.begin(); i < 100; ++i, ++aIter)
            cout << setw(20) << (*aIter)[0] << setw(15) << (*aIter)[9] << endl;
        break;

    case 'b':  // bubblesort with pointers
        row = new vector<string>;
        while (readMultiwordVector(*row, infile))
        {
            bTable.push_front(row);
            row = new vector<string>;
        }
        for (bIter = bTable.begin(); bIter != bTable.end(); ++bIter)
        {
            for (i = 0; i < (*(*bIter)).size(); ++i)
                space += (*(*bIter))[i].size();
            space += 2 * sizeof(int *);
        }

        cout << "sorting..." << endl;
        start = clock();
        bubblesort(bTable, before2);
        finish = clock();
        for (i = 0, bIter = bTable.begin(); i < 100; ++i, ++bIter)
            cout << setw(20) << (*(*bIter))[0] << setw(15) << (*(*bIter))[9] << endl;
        break;

    case 'c':  // quicksort with singly-linked list with elements
    	while (readMultiwordVector(line, infile))
    	            aTable.push_front(line);
    	aIter = aTable.begin();
    	for (int m = 0; m < (*aIter).size(); ++m)
    	{
    		space += (*aIter)[m].size();
    	    space += sizeof(int *);
    	}

    	cout << "sorting..." << endl;
    	start = clock();
    	quicksort(aTable, before1);
    	finish = clock();

    	for (i = 0, aIter = aTable.begin(); i < 100; ++i, ++aIter)
    	 	cout << setw(20) << (*aIter)[0] << setw(15) << (*aIter)[9] << endl;

    	break;
    }

    time = (double(finish)-double(start))/CLOCKS_PER_SEC;

    cout << "sort time: " << time << endl;
    cout << "space used: " << space << endl;

    return 0;
}

